﻿#include "pch.h"
#include "opencv2/opencv.hpp"
#include <opencv2/core/core.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include <opencv2/imgproc/imgproc.hpp> 
#include <opencv2/features2d/features2d.hpp>


using namespace cv;
using namespace std;

int labelTargets(Mat &src, Mat &mask, int thresh) {
	//以下是图像分割
	Mat seg = mask.clone();

	vector<vector<Point>> cnts;

	findContours(seg, cnts, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

	//以下进行筛选
	float area;
	Rect rect;
	int count = 0;
	string strCount;
	for (int i = cnts.size() - 1; i >= 0; i--) {
		vector<Point> c = cnts[i];
		area = contourArea(c);
		if (area < thresh) {//滤除面积小于thresh的结果，可能是噪声
			continue;
		}
		count++;//统计运动目标数量

		rect = boundingRect(c);
		//在原始图像上画出包围矩形，并给每个矩形标号
		rectangle(src, rect, Scalar(0, 0, 0xff), 1);

		stringstream ss;
		ss << count;
		ss >> strCount;

		putText(src, strCount, Point(rect.x, rect.y), CV_FONT_HERSHEY_PLAIN, 0.4, (0, 255, 0), 1);
	}
	return count;
}

/*
第三周进阶作业第一题：1. 在测试视频(OpenCV安装目录\sources\samples\data)上，使用基于混合高斯模型的背景提取算法，提取前景并显示(显示二值化图像，前景为白色)
*/
int backgroundSubtraction(void)
{
	const char* fn = "D:\\Program Files\\opencv\\sources\\samples\\data\\vtest.avi";
	VideoCapture cap;

	Mat source, image, foreGround,backGround,fgMask;

	Ptr<BackgroundSubtractor> pBgModel = createBackgroundSubtractorMOG2().dynamicCast<BackgroundSubtractor>();

	cap.open(fn);
	if (!cap.isOpened()) {
		cout << "无法打开视频文件：" << fn << endl;
	}
	for (;;) {
		cap >> source;
		if (source.empty()) {
			break;
		}

		resize(source, image, Size(source.cols / 2, source.rows / 2), INTER_LINEAR);

		if (foreGround.empty()) {
			foreGround.create(image.size(), image.type());
		}

		pBgModel->apply(image, fgMask);

		threshold(fgMask, fgMask, 30, 255, THRESH_BINARY);

		foreGround = Scalar::all(0);

		image.copyTo(foreGround, fgMask);

		int nTargets = labelTargets(image,fgMask,1);
		cout << "共检测到" << nTargets << "个目标" << endl;
		pBgModel->getBackgroundImage(backGround);

		//显示原始图像及背景，前景
		imshow("Source", image);
		imshow("Background", backGround);
		imshow("Foreground", foreGround);
		imshow("Foreground Mask", fgMask);

		//以下检测是否终止（按下ESC终止，对应ASCII 27）
		const char key = waitKey(100);
		if (key == 27) {
			break;
		}
	}

	waitKey(0);
	return 0;
}





void main() {
	backgroundSubtraction();
}